package com.lbh.structures.math;

import com.alibaba.fastjson.annotation.JSONField;
import com.sun.jna.Structure;

import java.util.Arrays;
import java.util.List;

/***
 * project:JRuntime
 * package:com.lbh.structures
 *
 * @author user:lenovo QQ:1601078366
 * @date 2021/10/18 0:16
 * @version V1.0
 */
@SuppressWarnings({"Duplicates", "MethodDoesntCallSuperMethod", "AlibabaConstantFieldShouldBeUpperCase", "unused"})
public class Vector3 implements Cloneable {

    @JSONField(name = "x")
    public float x;
    @JSONField(name = "y")
    public float y;
    @JSONField(name = "z")
    public float z;

    public static final Vector3 zero = new Vector3(0.0F, 0.0F, 0.0F);
    public static final Vector3 up = new Vector3(0.0F, 1.0F, 0.0F);
    public static final Vector3 down = new Vector3(0.0F, -1.0F, 0.0F);
    public static final Vector3 left = new Vector3(1.0F, 0.0F, 0.0F);
    public static final Vector3 right = new Vector3(-1.0F, 0.0F, 0.0F);
    public static final Vector3 forward = new Vector3(0.0F, 0.0F, 1.0F);
    public static final Vector3 back = new Vector3(0.0F, 0.0F, -1.0F);

    public Vector3(){
        x = 0.0F; y = 0.0F; z = 0.0F;
    }

    public Vector3(float x, float y, float z){
        this.x = x; this.y = y; this.z = z;
    }

    @Override
    public Vector3 clone() {
        return new Vector3(x, y, z);
    }

    public Vector3 add(Vector3 vec){
        x += vec.x; y += vec.y; z += vec.z;
        return this;
    }

    public Vector3 sub(Vector3 vec){
        x -= vec.x; y -= vec.y; z -= vec.z;
        return this;
    }

    public Vector3 mul(float v){
        x *= v; y *= v; z *= v;
        return this;
    }

    public Vector3 mul(Vector3 vec){
        x *= vec.x; y *= vec.y; z *= vec.z;
        return this;
    }

    public Vector3 div(Vector3 vec){
        x /= vec.x; y /= vec.y; z /= vec.z;
        return this;
    }

    public float magnitude(){
        return Mathf.sqrt(x * x + y * y + z * z);
    }

    public float magnitudeSqr(){
        return x * x + y * y + z * z;
    }

    public float dot(Vector3 vec){
        return x * vec.x + y * vec.y + z * vec.z;
    }

    public Vector3 cross(Vector3 vec){
        return new Vector3(y * vec.z - z * vec.y, z * vec.x - x * vec.z, x * vec.y - y * vec.x);
    }

    public Vector3 rotateX(float angle){
        float vsin, vcos, tmp;
        vsin = Mathf.sin(angle * 0.01745329251994329547F);
        vcos = Mathf.cos(angle * 0.01745329251994329547F);
        tmp = z * vsin + y * vcos;
        z = z * vcos - y * vsin;
        y = tmp;
        return this;
    }

    public Vector3 rotateY(float angle){
        float vsin, vcos, tmp;
        vsin = Mathf.sin(angle * 0.01745329251994329547F);
        vcos = Mathf.cos(angle * 0.01745329251994329547F);
        tmp = z * vsin + x * vcos;
        z = z * vcos - x * vsin;
        x = tmp;
        return this;
    }

    public Vector3 rotateZ(float angle){
        float vsin, vcos, tmp;
        vsin = Mathf.sin(angle * 0.01745329251994329547F);
        vcos = Mathf.cos(angle * 0.01745329251994329547F);
        tmp = x * vcos - y * vsin;
        y = x * vsin + y * vcos;
        x = tmp;
        return this;
    }

    public Vector3 normal(){
        float div = 1.0F / magnitude();
        return new Vector3(x * div, y * div, z * div);
    }

    public Vector3 normalize(){
        float div = 1.0F / magnitude();
        x *= div; y *= div; z *= div;
        return this;
    }
}
